<template>
  <a-button
    type="link"
    style="text-align: left; padding: 0"
    v-if="templateName && !disabled"
    @click="downloadTemplate"
    >点击下载指导导则模版</a-button
  >
  <a-upload-dragger
    v-if="!props.buttonText"
    v-bind="props"
    v-model:fileList="fileList"
    :beforeUpload="handleBeforeUpload"
    name="file"
    :customRequest="customRequest"
    :class="{
      hidden: isInTableComp && fileList?.length === props.maxCount,
    }"
    @preview="handlePreview"
    @change="handleChange"
  >
    <p class="ant-upload-drag-icon">
      <inbox-outlined></inbox-outlined>
    </p>
    <p class="ant-upload-text">请点击或拖拽文件至此区域上传</p>
    <p class="ant-upload-hint" v-if="tip">
      {{ tip }}
    </p>
  </a-upload-dragger>
  <a-upload
    v-else
    v-bind="props"
    v-model:fileList="fileList"
    :beforeUpload="handleBeforeUpload"
    :class="{
      hidden: isInTableComp && fileList?.length === props.maxCount,
    }"
    name="file"
    :customRequest="customRequest"
    @preview="handlePreview"
    @change="handleChange"
  >
    <a-button :disabled="disabled">
      <upload-outlined></upload-outlined>
      {{ props.buttonText }}
    </a-button>
  </a-upload>
</template>
<script lang="ts" setup>
import { useHttpInstance } from "@/hooks/useHttpInstance";
import { message } from "ant-design-vue";
import { AxiosRequestConfig } from "axios";
import { inject, ref, watch } from "vue";
import { downloadByBlob } from "@/utils";
import { UploadRequestOption } from "ant-design-vue/es/vc-upload/interface";
import { uploadFile } from "@/api";
const isInTableComp = inject<boolean>("isInTableComp");
const props = defineProps<{
  templateName?: string;
  requestParams?: AxiosRequestConfig;
  tip?: string;
  value?: any[];
  accept?: string;
  maxCount?: number;
  disabled?: boolean;
  placeholder?: string;
  listType?: string;
  multiple?: boolean;
  buttonText?: string;
  style?: any;
}>();
const emit = defineEmits<{ (event: "update:value", value: any): void }>();
const fileList = ref();
watch(
  () => props.value,
  (val) => {
    if (val) {
      fileList.value = val.map((item) => ({
        uid: item.id,
        name: item.filename,
        status: "done",
        response: item,
        url: "/file/read/" + item.id,
      }));
    }
  },
  {
    immediate: true,
  }
);
const handleChange = ({ file, fileList }: { file: any; fileList: any[] }) => {
  if (file.status === "done") {
    emit(
      "update:value",
      fileList.map((item) => item.response)
    );
  }
};
const handleBeforeUpload = (res: File) => {
  if (
    props.accept &&
    !props.accept
      .split(",")
      .every((suffix: string) => !res.name.endsWith(suffix))
  ) {
    message.error(props.tip);
    return false;
  }
  return true;
};
const http = useHttpInstance();
const downloadTemplate = () => {
  if (props.requestParams?.url?.startsWith("http")) {
    window.open(props.requestParams.url);
  } else {
    http
      .getReq(Object.assign({ responseType: "blob" }, props.requestParams))
      .then((res: Blob) => {
        downloadByBlob(new Blob([res]), props.templateName || "模版");
      });
  }
};
const customRequest = (option: UploadRequestOption) => {
  const formData = new FormData();

  if (option.data) {
    Object.keys(option.data).forEach((key) => {
      const value = option.data?.[key];
      // support key-value array data
      if (Array.isArray(value)) {
        value.forEach((item) => {
          // { list: [ 11, 22 ] }
          // formData.append('list[]', 11);
          formData.append(`${key}[]`, item);
        });
        return;
      }

      formData.append(key, value as string | Blob);
    });
  }
  if (option.filename) {
    // eslint-disable-next-line no-undef
    if (option.file instanceof Blob) {
      formData.append(option.filename, option.file, (option.file as any).name);
    } else {
      formData.append(option.filename, option.file);
    }
  }
  return uploadFile(formData, {
    onDownloadProgress: (e) => {
      if (e.total && e.total > 0) {
        e.rate = (e.loaded / e.total) * 100;
      }
      option.onProgress?.({ ...e, percent: e.rate });
    },
  })
    .then((res) => {
      option.onSuccess?.(res);
    })
    .catch(option.onError);
};
const handlePreview = async (file: any) => {
  if (!file.url && !file.preview) {
    file.preview = window.URL.createObjectURL(file.originFileObj);
  }
  window.open(file.url || file.preview);
};
</script>
<style lang="scss" scoped>
.hidden {
  display: inline-block;
  :deep(.ant-upload) {
    display: none;
  }
}
.ant-form-item-control-input-content > span {
  display: inline-block;
  :deep(.ant-upload-disabled) {
    display: none !important;
  }
}
</style>
